home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / Edition Manager / main.c < prev    next >
Encoding:
Text File  |  1991-02-20  |  67.7 KB  |  1,551 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #   Apple Developer Technical Support
  4. #
  5. #   Edition Manager Sample Application
  6. #
  7. #   EditionSample
  8. #
  9. #   main.c  -   C Source
  10. #
  11. #   Copyright © 1990,1991 Apple Computer, Inc.
  12. #   All rights reserved.
  13. #
  14. #   Versions:   
  15. #               2.0ß1                02/91       C.K. Haun <TR>
  16. #   
  17. #   Components:
  18. #                           main.c
  19. #                           Menu.c
  20. #                           Files.c
  21. #                           Publish.c
  22. #                           Subscribe.c
  23. #                           TextSections.c
  24. #                           Windows.c
  25. #                           AppleEventM.c
  26. #                           EditionSample.make
  27. #                           EditionSample.r
  28. #                            FinderIcons.r
  29. #                           EdSampdefines.h
  30. #                           BuildHeaders.c
  31. #
  32. #
  33. #   This is an example of using the Edition Manager in a multi-windowed
  34. #   application.
  35. #   This sample contains most of the Edition Manager calls that
  36. #   you'll need in your application.  It also contains one method
  37. #   for keeping track of the edition data for all your documents.
  38. #   It does NOT by any means demonstrate all the techniques 
  39. #   you need for a large application, nor the best data handling 
  40. #   methods for all cases.  
  41. #   Use this sample as a starting point, and adapt its' routines to 
  42. #   meet the specific needs of your project.  
  43. #   This sample will grow as more edition types are implemented,
  44. #   periodically check AppleLink for a later, expanded sample.
  45. #   This application is an example of the form of a Macintosh 
  46. #   application; it is NOT a template. It is NOT intended to be 
  47. #   used as a foundation for the next world-class, best-selling, 
  48. #   600K application. A stick figure drawing of the human body may 
  49. #   be a good example of the form for a painting, but that does not 
  50. #   mean it should be used as the basis for the next Mona Lisa.
  51. #
  52. #
  53. ------------------------------------------------------------------------------*/
  54. /*****************************************************************
  55. We here at DTS believe that good sample code is one of the best tools
  56. we can provide  to help make your jobs easier.  And we want the
  57. code we provide to be the best possible, and to be the most useful.
  58. You can help us.
  59. Please take a few minutes and answer the following questions about this 
  60. piece of sample code.  When you're done, cut out the survey and
  61. send it to the AppleLink account DTS.FEEDBACK, 
  62. internet DTS.FEEDBACK@AppleLink.apple.com
  63. or by US mail to;
  64. DTS Sample Code Feedback
  65. 20525 Mariani Ave., MS: 75-3T
  66. Cupertino, CA 95014
  67. We won't be able to answer individual feedback messages, but you'll
  68. see the difference in the code we put out.
  69. Your answers will help us help you write fantastic applications!
  70.  
  71. -------------------------------- cut here ---------------------------------
  72. 1) Sample goals  
  73. All our sample code is written to meet a need, to show a specific manager
  74. or system feature.  
  75. Does this sample you're now looking at meet it's objectives?  Does it show
  76. you the features of the Edition Manager that you need to write your 
  77. application?  If not, please tell us what we could do better.
  78.  
  79.  
  80. 2) Sample Organization
  81. Is this sample organized in a manner that makes it easy for you to find the
  82. information you need?  If you're looking for a particular routine or
  83. trap call, can you find it quickly or do you have to search too much?
  84. Any organizational comments on file names, MPW marks, function names, or
  85. anything else?
  86.  
  87.  
  88. 3) Useability
  89. Can you use the code in this sample in your application?  We'd love for
  90. all our sample code to be 'cut and paste' code that you can drop right into
  91. your code, did we meet that goal (language differences aside)?
  92.  
  93.  
  94. 4) Programmer's Style
  95. Programming is an individual art, and every programmer writes code differently.
  96. But some coding styles can hide more than they help.
  97. Could you follow the logic of the programmer of this sample?  Was the point of
  98. the code clear, not hidden by language peculiarities?
  99.  
  100.  
  101. 5) Program line Comments
  102. Are there enough comments in this sample?  Are there too many comments?
  103. Did the comments in the code help you clearly understand the process and logic?
  104.  
  105.  
  106. 6) Building
  107. Did this sample compile?  Did you have any problem building and running this 
  108. sample (in the environment it was meant to be built/run under)?
  109.  
  110.  
  111. 7) Bugs
  112. And of course, were there any bugs?  
  113.  
  114.  
  115. 8) Your wish list
  116. What other specific areas would you like to see covered in DTS sample code?
  117.  
  118.  
  119. 9 - ∞) Any additional comments?
  120.  
  121.  
  122. -------------------------------- cut here ---------------------------------
  123. Again, thanks a lot for any and all feedback you can send us.  Your input 
  124. will shape our future code; the more information you can give us the
  125. better service we can provide to you.
  126.  
  127. Apple Developer Tech Support
  128. ***********************************************************************/
  129.  
  130.  
  131. /* Picture display and publisher */
  132. /* will be extended to be a text and private pub pub pub pppppub */
  133. #define __SAMPMAIN__
  134.  
  135. #pragma segement Main
  136. #pragma load "EdSampheaders"                                /* see the Buildheaders.c file */
  137.  
  138. #include "EdSampdefines.h"
  139.  
  140. /* prototypes for this file */
  141. void CloseMyWindow(WindowPtr theClose);
  142. void DoDiskEvents(long dinfo);
  143. void DrawIt(void);
  144. void StartStuff(void);
  145. void UndoLast(void);
  146. void DrawMe(void);
  147. WindowPtr AddNewWindow(Boolean showIt);
  148. Boolean SearchPubs(Point thePoint);
  149. Boolean SearchSubs(Point thePoint);
  150. void ShowMe(Str255 in, OSErr aevtErr);
  151. void DrawFull(windowCHandle theWind, WindowPtr theWindPtr);
  152. void AddLine(windowCHandle nowHandle, myLine *inline);
  153. void AddRect(windowCHandle nowHandle, Rect *inrect);
  154. void AddTextBox(windowCHandle nowHandle, Rect *inrect);
  155. void AddOval(windowCHandle nowHandle, Rect *inoval);
  156. void AddSelection(windowCHandle nowHandle, Rect *inrect);
  157. void AdjustCursor(Point mouse, RgnHandle region, Boolean isAppleEvent);
  158. void DoDocumentClick(WindowPtr twindow);
  159. void PullRect(windowCHandle theWind, Rect *startRect, Boolean isOval, Boolean useRect);
  160. void CreateClipBoard(void);
  161. extern void DrawClip(WindowPtr windowIn);
  162. extern void ClipClick(WindowPtr twindow);
  163. extern void CloseClip(void);
  164. extern void UpdateScrap(void);
  165. extern void SpitClip(void);
  166. void DeBorderSelection(void);
  167. OSErr MySetHandleSize(Handle theHandle, Size theSize);
  168. Boolean InTextBox(windowCHandle inName, Rect *where);
  169. void MakeRect(Point *aPoint, Point *bPoint, Rect *putRect);
  170. Boolean PureCursor(char theKey);
  171. /* external references */
  172. extern void SaveMe(windowCHandle theWind, WindowPtr theWindPtr);
  173. extern Boolean DoSelected(long val);
  174. extern ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem);
  175. extern void PopMenu(Point tp);
  176. extern void WriteNum(long numtowrite);
  177. extern void DoHighLevel(EventRecord AERecord);
  178. extern void InitAEStuff(void);
  179. extern void SetUndo(short undoNow, Boolean fromRecord);
  180. extern void DoOptions(SectionHandle inSection);
  181. extern void SetWMenus(Boolean how);
  182. extern void AdjustMenus(windowCHandle tempCH);
  183. extern void KillClipSub(void);
  184. extern void _DataInit();
  185. extern OSErr MyGoToPublisher(SectionHandle theSection);
  186. extern void CheckTextSections(windowCHandle inWindow, short Action);
  187. extern Boolean SkipOverSubscriber(windowCHandle inWindow, unsigned short theKey);
  188. extern void CheckSectionHit();
  189. extern void ExcludeSubscriber(windowCHandle tempCH);
  190. extern void BorderTextSection(textSectionHandle theText);
  191. extern void ChangePlane(WindowPtr twindow);
  192. extern Boolean IsDAWindow(WindowPtr window);
  193. extern Boolean IsAppWindow(WindowPtr window);
  194. extern WindowPtr AddNewWindow(Boolean showIt);
  195. extern void CloseMyWindow(WindowPtr theClose);
  196. /* globals */
  197.  
  198. Handle gMymenu;                                             /* my menu bar handle */
  199. Handle gScrapData;                                          /* picture data currently on clipboard */
  200. /* individual menu handles */
  201. MenuHandle gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gToolMenuHandle, gAdditionalMenu;
  202. Boolean gStop;                                              /* Stop flag for this app */
  203. WindowPtr gCurrentWindow = nil;                             /* window currently frontmost */
  204. WindowPtr gClipWindowPtr = nil;                             /* our clipboard window */
  205. WindowPtr gActionWindows = nil;                             /* start of our window list */
  206. short gWindowCount = 0;                                     /* current number of windows, since I'm restricting to 10 */
  207. unsigned long gMasterWindowID = 10000;                      /* for section tracking */
  208. Rect gShowPubRect;                                          /* rectangle of the currently selected publisher */
  209. Rect gShowSubRect;                                          /* rectangle of the currently selected subscriber */
  210. SectionHandle gShowingSecHandle = nil;                      /* currently selected section */
  211. SectionHandle gClipSection = nil;                           /* if the clipboard contains a section */
  212. PicHandle gClipPict;                                        /* for the section picture */
  213. Boolean gShowPub = false;                                   /* telling if a publisher or subscriber */
  214. Boolean gShowSub = false;                                   /* border should be displayed */
  215. Boolean gShowingAll = false;                                /* show all borders toggle */
  216. Boolean gInBackground = false;                              /* Where Are We? */
  217. Boolean gExpanded = false;                                  /* flag for expanded dialogs, for this sample */
  218. Boolean gResizeSub = false;                                 /* resize flag for this sample */
  219. short gClipHasContents = kClipEmpty;                        /* indicates the contents of the clipboard (PICT, TEXT, section ) */
  220. EventRecord gERecord;                                       /* guess */
  221. ProcessSerialNumber gOurSN;                                 /* serial number of this process (us, our application) */
  222. Boolean gHasAppleEvents;                                    /* not really necessary, since we fail if these */
  223. Boolean gHasEditionManager;                                 /* aren't available, but it's only two bytes.... */
  224. Boolean gHasSelection = false;                              /* for publish menu item */
  225. Boolean gEdSamp = false;                                    /* allow subscription to MacPaint files */
  226. EditionOpenerProcPtr gOriginalOpener;                       /* for custom opener, later.... */
  227.  
  228. short actsToIDs[6] =                                        /* converts my action codes to tool menu item IDs */
  229. {
  230.     0, 1, 2, 3, 4, 6
  231. };
  232.  
  233.  
  234.  
  235.  
  236. long aLong;
  237. SectionHandle lastSection;                                  /* for double click testing */
  238. unsigned long lastSecClickTick;
  239.  
  240. main()
  241. {
  242.     WindowPtr twindow;
  243.     Boolean x;
  244.     Boolean menuAction;
  245.     windowCHandle tempCH;                                   /* temporary var */
  246.     RgnHandle mousergn;                                     /* for WaitNextEvent */
  247.     PScrapStuff theScrap;
  248.     short myScrapCount = 999;                               /* intialize to a silly value */
  249.     UnloadSeg((Ptr)_DataInit);                              /* throw the bums out */
  250.     StartStuff();                                           /* initialize managers and normal startup actions */
  251.     UnloadSeg((Ptr)StartStuff);
  252.     theScrap = InfoScrap();
  253.     FlushEvents(everyEvent, 0);
  254.     mousergn = NewRgn();
  255.     gStop = false;
  256.     while (!gStop) {
  257.         x = WaitNextEvent(everyEvent, &gERecord, 30, mousergn);
  258.         theScrap = InfoScrap();
  259.         if (theScrap->scrapCount != myScrapCount) {
  260.             myScrapCount = theScrap->scrapCount;
  261.             UpdateScrap();
  262.         }
  263.         if (gCurrentWindow != nil) {
  264.             TEHandle tempTE;
  265.             windowCHandle tempCH = (windowCHandle)GetWRefCon(gCurrentWindow);
  266.             tempTE = (*tempCH)->boxHandle;
  267.             if (tempTE != nil)
  268.                 TEIdle(tempTE);
  269.         }
  270.         AdjustCursor(gERecord.where, mousergn, (gERecord.what == kHighLevelEvent));
  271.         switch (gERecord.what) {
  272.             case nullEvent:
  273.                 /* no nul processing in this sample */
  274.                 break;
  275.             case updateEvt:
  276.                 DrawIt();                                   /* draw whatever window needs an update */
  277.                 break;
  278.             case mouseDown:
  279.                 /* first see where the hit was */
  280.                 switch (FindWindow(gERecord.where, &twindow)) {
  281.                     case inDesk:                            /* if they hit in desk, then the process manager */
  282.                         break;                              /* will switch us out, we don't need to do anything */
  283.                     case inMenuBar:
  284.                         /* If they clicked in the menu bar, we need to set up the Undo */
  285.                         /* text string for the current window, and the toggle of */
  286.                         /* Publisher or Subscriber options before we drop the */
  287.                         /* menu down. */
  288.                         /* Also change the Save string depending on the save state */
  289.                         /* Pull our aux data structure out of the current window */
  290.                         if (gCurrentWindow) {
  291.                             tempCH = (windowCHandle)GetWRefCon(gCurrentWindow);
  292.                             HLock((Handle)tempCH);          /* lock it */
  293.                             gHasSelection = (*tempCH)->hasSelection;
  294.                             AdjustMenus(tempCH);            /* in menu.c */
  295.                             HUnlock((Handle)tempCH);
  296.                         } else {
  297.                             AdjustMenus(nil);
  298.                         }
  299.                         /* Now we drop the menu down, and pass the results */
  300.                         /* to our menu handler (in Menu.c) */
  301.                         DoSelected(MenuSelect(gERecord.where));
  302.                         break;
  303.                     case inSysWindow:
  304.                         /* pass to the system */
  305.                         SystemClick(&gERecord, twindow);
  306.                         break;
  307.                     case inContent:
  308.                         /* Our major workarea.  Depending on other factors, a */
  309.                         /* user could be drawing, moving a subscriber, selecting */
  310.                         /* a publisher or subscriber, selecting an area, or nothing. */
  311.                         /* First, if they did not click in the front window, we need */
  312.                         /* to bring the window they did click in to the front, and */
  313.                         /* pull the information we need (cursor mode, undo action, etc. ) */
  314.                         /* out of the aux record and update things */
  315.                         if (twindow != FrontWindow()) {
  316.                             ChangePlane(twindow);
  317.                         } else {
  318.                             if (gCurrentWindow) {           /* don't do this unless we have a window open, silly */
  319.                                 windowCHandle clicker;
  320.                                 clicker = (windowCHandle)GetWRefCon(twindow);
  321.                                 /* jump to the content function stored for this window */
  322.                                 HLock((Handle)clicker);     /* lock it down so things don't get stupid */
  323.                                 (ProcPtr)((*clicker)->clickMe)(twindow);
  324.                                 HUnlock((Handle)clicker);       /* all done */
  325.                             }
  326.                         }
  327.                         break;
  328.                     case inDrag:
  329.                         DragWindow(twindow, gERecord.where, &qd.screenBits.bounds);
  330.                         break;
  331.                     case inGrow:
  332.                     case inGoAway:
  333.                         /* Track a click in the go away box.  If the user stays in it, */
  334.                         /* call the close proc for this window */
  335.                         if (TrackGoAway(twindow, gERecord.where))
  336.                             (ProcPtr)((*(windowCHandle)((WindowPeek)twindow)->refCon)->closeMe)(twindow);
  337.                         break;
  338.                         
  339.                 }
  340.             case mouseUp:
  341.                 /* don't care */
  342.                 break;
  343.                 /* same action for key or auto key */
  344.             case keyDown:
  345.             case autoKey:
  346.                 /* Do menu commands.  */
  347.                 /* Also check the window record for a TextEdit field, if there */
  348.                 /* is one pass the key to it */
  349.                 if (gERecord.modifiers & cmdKey) {
  350.                     if (gCurrentWindow) {
  351.                         tempCH = (windowCHandle)GetWRefCon(gCurrentWindow);
  352.                         HLock((Handle)tempCH);              /* lock it */
  353.                         gHasSelection = (*tempCH)->hasSelection;
  354.                         AdjustMenus(tempCH);                /* in menu.c */
  355.                         HUnlock((Handle)tempCH);
  356.                     } else {
  357.                         AdjustMenus(nil);
  358.                     }
  359.                     DoSelected(MenuKey(gERecord.message & charCodeMask));
  360.                 } else {
  361.                     WindowPtr tempWP = FrontWindow();
  362.                     tempCH = (windowCHandle)GetWRefCon(tempWP);
  363.                     if (IsAppWindow(tempWP) && ((*tempCH)->boxHandle != nil)) {
  364.                         Boolean wasPC = false;
  365.                         tempCH = (windowCHandle)GetWRefCon(tempWP);
  366.                         if ((*tempCH)->textSections != nil) {
  367.                             /* this text box has sections, and the sections may need to be */
  368.                             /* adjusted by this keystroke.  First, see if it's a pure cursor move, */
  369.                             if (wasPC = PureCursor(gERecord.message & charCodeMask))
  370.                                 wasPC = SkipOverSubscriber(tempCH, gERecord.message & charCodeMask);
  371.                             else
  372.                                 CheckTextSections(tempCH, kKeyStroke);
  373.                         }
  374.                         if (!wasPC) {
  375.                             /* ExcludeSubscriber shortens the current selection if it impact on any */
  376.                             /* subscribers */
  377.                             ExcludeSubscriber(tempCH);
  378.                             TEKey(gERecord.message & charCodeMask, (*tempCH)->boxHandle);
  379.                         }
  380.                     }
  381.                 }
  382.                 break;
  383.             case keyUp:
  384.                 /* don't care */
  385.                 break;
  386.             case diskEvt:
  387.                 /* I don't do anything special for disk events, this just passes them */
  388.                 /* to a function that checks for an error on the mount */
  389.                 DoDiskEvents(gERecord.message);
  390.                 break;
  391.             case activateEvt:
  392.                 /* Draws on a window activate.  Other activate/deactivate stuff is */
  393.                 /* handled in either the ChangePlane function (for normal shuffling ) */
  394.                 /* or in the suspend/resume handler for layer swaps */
  395.                 if (gERecord.modifiers & activeFlag)
  396.                     DrawIt();
  397.                 break;
  398.             case networkEvt:
  399.                 /* don't care */
  400.                 break;
  401.             case driverEvt:
  402.                 /* don't care */
  403.                 break;
  404.             case app4Evt:
  405.                 switch ((gERecord.message >> 24) & 0x0FF) {     /* high byte of message */
  406.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  407.                         gInBackground = (gERecord.message & kResumeMask) == 0;
  408.                         if (gInBackground) {
  409.                             SpitClip();                     /* export the clipboard please */
  410.                             /* deactivate the current TextEdit record as necessary */
  411.                             if (gCurrentWindow != nil) {
  412.                                 windowCHandle tempCH = (windowCHandle)GetWRefCon(gCurrentWindow);
  413.                                 if ((*tempCH)->boxHandle != nil)
  414.                                     TEDeactivate((*tempCH)->boxHandle);
  415.                             }
  416.                             if (gShowSub || gShowPub) {
  417.                                 
  418.                             }
  419.                         } else {
  420.                             if (gCurrentWindow != nil) {
  421.                                 windowCHandle tempCH = (windowCHandle)GetWRefCon(gCurrentWindow);
  422.                                 if ((*tempCH)->boxHandle != nil)
  423.                                     TEActivate((*tempCH)->boxHandle);
  424.                             }
  425.                         }
  426.                         break;
  427.                 }
  428.                 break;
  429.             default:
  430.                 break;
  431.                 /* This dispatches high level events (AppleEvents, for example) */
  432.                 /* to our dispatch routine.  This is NEW in the event loop for */
  433.                 /* System 7 */
  434.             case kHighLevelEvent:
  435.                 DoHighLevel(gERecord);
  436.                 break;
  437.                 
  438.         }
  439.     }
  440. }
  441.  
  442. /* DrawIt calls the drawing routine for the window that requires a refresh,
  443. * either for a update or activate 
  444. */
  445. void DrawIt(void)
  446. {
  447.     WindowPtr nowwind, tempwind;
  448.     windowCHandle drawers;
  449.     GetPort(&tempwind);                                     /* save the current port */
  450.     nowwind = (WindowPtr)gERecord.message;                  /* get the port referenced by 
  451.                                                                                                this event */
  452.     BeginUpdate(nowwind);                                   /* tell window manager to do it's thing */
  453.     SetPort(nowwind);
  454.     EraseRgn(nowwind->visRgn);                              /* erase whatever needs updating, remember that
  455.                                                             BeginUpdate copies the update region into the visRgn */
  456.     /* pull our control structure out of the refCon */
  457.     drawers = (windowCHandle)GetWRefCon(nowwind);
  458.     HLock((Handle)drawers);                                 /* lock it down so things don't get stupid */
  459.     /* jump to the drawing function stored for this window */
  460.     (ProcPtr)((*drawers)->drawMe)(drawers, nowwind);
  461.     HUnlock((Handle)drawers);                               /* all done */
  462.     EndUpdate(nowwind);                                     /* all done */
  463.     SetPort(tempwind);                                      /* reset the port to the entry port */
  464. }
  465.  
  466. /* DrawIt */
  467.  
  468. /* UndoLast undoes the last drawing action that happened in the current 
  469. * window.  Each window has it's own record of the last action, so 
  470. * Undo is always valid for the current window, and will not act on a 
  471. * window the user doesn't expect. */
  472. void UndoLast(void)
  473. {
  474.     windowCHandle temp;
  475.     WindowPtr tempPort;
  476.     GetPort(&tempPort);                                     /* not really necessary, but I'm paranoid */
  477.     SetPort(gCurrentWindow);
  478.     temp = (windowCHandle)GetWRefCon(gCurrentWindow);
  479.     HLock((Handle)temp);                                    /* memory may move when handles are resized */
  480.     switch ((*temp)->undoAction) {                          /* last action that happened in this window */
  481.         /* For the graphic objects, we need to erase the last thing draw and update
  482.         * the window record's handles and counts */
  483.         case kDrawLine:
  484.             HUnlock((Handle)(*temp)->lineList);
  485.             (*temp)->lineCount--;
  486.             MySetHandleSize((Handle)(*temp)->lineList, GetHandleSize((Handle)(*temp)->lineList) - sizeof(myLine));
  487.             break;
  488.         case kDrawRect:
  489.             (*temp)->rectCount--;
  490.             HUnlock((Handle)(*temp)->rectList);
  491.             MySetHandleSize((*temp)->rectList, GetHandleSize((*temp)->rectList) - sizeof(Rect));
  492.             break;
  493.         case kDrawOval:
  494.             (*temp)->ovalCount--;
  495.             HUnlock((Handle)(*temp)->ovalList);
  496.             MySetHandleSize((*temp)->ovalList, GetHandleSize((*temp)->ovalList) - sizeof(Rect));
  497.             break;
  498.         case kTextBox:
  499.             TEDispose((*temp)->boxHandle);
  500.             (*temp)->boxHandle = nil;
  501.             InsetRect(&(*temp)->textBox, -3, -2);           /* just don't ask */
  502.             InvalRect(&(*temp)->textBox);
  503.             break;
  504.         case kSelectStuff:
  505.             (*temp)->hasSelection = false;
  506.             break;
  507.     }
  508.     HUnlock((Handle)temp);
  509.     /* now make sure things get refreshed */
  510.     InvalRect(&(gCurrentWindow->portRect));
  511.     EraseRect(&(gCurrentWindow->portRect));
  512.     SetUndo(0, false);
  513.     SetPort(tempPort);
  514. }
  515.  
  516.  
  517.  
  518. /* In SearchPubs we'll search the publishers in this window for a publisher */
  519. /* that was clicked in.  If we find one, hilite it and outline it. */
  520. /* Point is already in local coordinates */
  521. Boolean SearchPubs(Point thePoint)
  522. {
  523.     register qq;
  524.     Rect rectToCheck;
  525.     Rect cornerRect;
  526.     Rect *theRects;
  527.     Boolean gotIt = false;
  528.     windowCHandle shortname = (windowCHandle)GetWRefCon(gCurrentWindow);
  529.     HLock((Handle)shortname);
  530.     if ((*shortname)->numPubs) {                            /* does this window have any publishers? */
  531.         /* yes, see if one was clicked in */
  532.         HLock((*shortname)->pubRects);                      /* lock the rect handle down */
  533.         theRects = (Rect *)*(*shortname)->pubRects;
  534.         /* dereference it and cast it to a rect pointer so checking will be 
  535.         *   conceptually easier (i.e. you can read it) 
  536.         */
  537.         for (qq = 0; qq < (*shortname)->numPubs; qq++) {        /* step through 'em */
  538.             SectionHandle *tempPtr;
  539.             rectToCheck = *theRects;
  540.             if (PtInRect(thePoint, &rectToCheck)) {         /* thePoint is coming from your */
  541.                 /* last event record */
  542.                 /* We've found a section that has been clicked in */
  543.                 if (gShowPub && (rectToCheck != gShowPubRect))
  544.                     InvalRect(&gShowPubRect);               /* clear previous, if there was one */
  545.                 gShowPub = true;
  546.                 if (gShowSub)                               /* clear previous, if there was one */ {
  547.                     InvalRect(&gShowSubRect);
  548.                     gShowSub = false;
  549.                 }
  550.                 /* make sure the border gets draw next update */
  551.                 InsetRect(&rectToCheck,-4,-4);
  552.                 InvalRect(&rectToCheck);
  553.                 InsetRect(&rectToCheck,4,4);
  554.                 /* we've found it with it's rectangle, so now dig out the */
  555.                 /* section handle */
  556.                 HLock((*shortname)->pubs);
  557.                 tempPtr = (SectionHandle *)*(*shortname)->pubs;
  558.                 tempPtr += qq;
  559.                 /* and move the section handle into our global variable that */
  560.                 /* contains the currently highlighted section, so we can */
  561.                 /* access it from the Options function and dialog */
  562.                 gShowingSecHandle = *tempPtr;
  563.                 /* done with the pointer handle */
  564.                 HUnlock((*shortname)->pubs);
  565.                 /* change the menu item name now */
  566.                 SetItem(gEditMenuHandle, kSoptionsItem, "\pPublisher Options...");
  567.                 gShowPubRect = rectToCheck;
  568.                 gotIt = true;
  569.                 /* Now we need to stretch the thing if the user wants too, I guess */
  570.                 /* See if it was in the corner rect first */
  571.                 cornerRect = gShowPubRect;
  572.                 cornerRect.top = cornerRect.bottom - 7;
  573.                 cornerRect.left = cornerRect.right - 7;
  574.                 if (PtInRect(thePoint, &cornerRect)) {
  575.                     PullRect(shortname, &gShowPubRect, false, true);
  576.                     if (*theRects != gShowPubRect) {
  577.                         *theRects = gShowPubRect;
  578.                         InvalRect(theRects);
  579.                     }
  580.                 }
  581.             }
  582.             if (gotIt)
  583.                 break;
  584.             theRects++;                                     /* increase by one Rect */
  585.         }
  586.         HUnlock((*shortname)->pubRects);
  587.     }
  588.     HUnlock((Handle)shortname);
  589.     return(gotIt);
  590. }
  591.  
  592. /* end SearchPubs */
  593.  
  594. /* Searches the subcriber list, hilites the selection, and drags it */
  595. /* This is very similar to the publisher check, but has added functionality */
  596. /* for dragging the subscriber around the window */
  597. Boolean SearchSubs(Point thePoint)
  598. {
  599.     register qq;
  600.     Handle *theRectsHandle;
  601.     Boolean subGotIt = false;
  602.     windowCHandle shortname = (windowCHandle)GetWRefCon(gCurrentWindow);
  603.     HLock((Handle)shortname);
  604.     if ((*shortname)->numSubs) {                            /* does it have any subscribers? */
  605.         HLock((*shortname)->subRects);                      /* lock down the rect handle */
  606.         /* cast it as a pointer to handles for reading ease */
  607.         theRectsHandle = (Handle *)*(*shortname)->subRects;
  608.         for (qq = 0; qq < (*shortname)->numSubs; qq++) {        /* step through the subscribers */
  609.             SectionHandle *tempPtr;
  610.             Rect *checkRect;
  611.             Rect cornerRect;
  612.             HLock(*theRectsHandle);
  613.             checkRect = (Rect *)**theRectsHandle;
  614.             /* did they click in this rect? */
  615.             InsetRect(checkRect, -4, -4);                   /* include the possible borders */
  616.             if (PtInRect(thePoint, checkRect)) {            /* yes */
  617.                 /* erase the old display rectangles, if there are any */
  618.                 if (gShowSub)
  619.                     InvalRect(&gShowSubRect);
  620.                 gShowSub = true;
  621.                 if (gShowPub) {
  622.                     InvalRect(&gShowPubRect);
  623.                     gShowPub = false;
  624.                 }
  625.                 /* get the section handle for this section */
  626.                 HLock((*shortname)->subs);
  627.                 tempPtr = (SectionHandle *)*(*shortname)->subs;
  628.                 tempPtr += qq;
  629.                 gShowingSecHandle = *tempPtr;
  630.                 HUnlock((*shortname)->subs);
  631.                 /* change the menu item name now */
  632.                 SetItem(gEditMenuHandle, kSoptionsItem, "\pSubscriber Options...");
  633.                 InvalRect(checkRect);                       /* make sure it gets redrawn */
  634.                 /* now I want the actual rect values so I can drag it around */
  635.                 /* in response to the user */
  636.                 gShowSubRect = *checkRect;
  637.                 PenPat(qd.dkGray);
  638.                 PenSize(3, 3);
  639.                 FrameRect(&gShowSubRect);
  640.                 PenSize(1, 1);
  641.                 /* Here you drag the thing around to where the user wants it, updating the 
  642.                 *   window record as you do it. */
  643.                 GetMouse(&thePoint);
  644.                 InvalRect(&gShowSubRect);
  645.                 /* two choices here.  They could be dragging the whole thing, or resizing it.  */
  646.                 /* The resize box is in the lower right ten pixels, I'll say, so if the original */
  647.                 /* click is there I'll go to the resize routine */
  648.                 cornerRect = gShowSubRect;
  649.                 cornerRect.top = cornerRect.bottom - 7;
  650.                 cornerRect.left = cornerRect.right - 7;
  651.                 if (PtInRect(thePoint, &cornerRect) && gResizeSub) {
  652.                     
  653.                     PullRect(shortname, &gShowSubRect, false, true);
  654.                     
  655.                 } else {
  656.                     while (StillDown()) {                   /* keep doing it until they release the mouse */
  657.                         Point tempPoint;
  658.                         PenMode(patXor);
  659.                         FrameRect(&gShowSubRect);           /* nasty way to put up a flashing border for the drag */
  660.                         FrameRect(&gShowSubRect);
  661.                         GetMouse(&tempPoint);
  662.                         /* keep inside the window please, don't let them drag the */
  663.                         /* rectangle outside the window bounds */
  664.                         if (PtInRect(tempPoint, &(gCurrentWindow->portRect))) {
  665.                             if (tempPoint != thePoint) {
  666.                                 OffsetRect(&gShowSubRect, tempPoint.h - thePoint.h, tempPoint.v - thePoint.v);
  667.                                 thePoint = tempPoint;
  668.                             }
  669.                         }
  670.                     }
  671.                     PenMode(srcCopy);
  672.                 }
  673.                 InvalRect(&gShowSubRect);
  674.                 InsetRect(checkRect, 4, 4);                 /* remember that ShowingRect is 4 bigger */
  675.                 InsetRect(&gShowSubRect, 4, 4);                 /* remember that ShowingRect is 4 bigger */
  676.  
  677.                 if (gShowSubRect != *checkRect) {           /* don't update if they didn't end up moving it */
  678.  
  679.  
  680.                         *checkRect = gShowSubRect;          /* update our record of things */
  681.                 }
  682.  
  683.                 
  684.                 
  685.                 subGotIt = true;
  686.             } else {
  687.             /* shrink it back agin */
  688.             InsetRect(checkRect, 4, 4);                 /* remember that ShowingRect is 4 bigger */
  689.  
  690.             }
  691.             HUnlock(*theRectsHandle);
  692.             theRectsHandle += 1;                            /* increase by one Rect to check next */
  693.             if (subGotIt)
  694.                 break;
  695.         }
  696.         HUnlock((*shortname)->subRects);
  697.     }
  698.     HUnlock((Handle)shortname);
  699.     return(subGotIt);
  700. }
  701.  
  702. /* end SearchSubs */
  703.  
  704. /* DrawFull draws the contents of your document windows */
  705.  
  706. void DrawFull(windowCHandle theWind, WindowPtr theWindPtr)
  707. {
  708.     register qq;
  709.     Rect scratchRect;
  710.     Rect *scratchRectPtr;
  711.     Rect grabRect;
  712.     /* Are there any lines in this window? */
  713.     if ((*theWind)->lineCount) {                            /* yes, draw 'em */
  714.         myLine scratchLine;
  715.         myLine *scratchPtr;
  716.         HLock((Handle)(*theWind)->lineList);                /* lock my line handle in my window data struct */
  717.         scratchPtr = (myLine *)*((*theWind)->lineList);     /* cast it to a pointer to my structure */
  718.         for (qq = 0; qq < (*theWind)->lineCount; qq++) {        /* loop through the lines */
  719.             scratchLine = *(scratchPtr + qq);               /* move the line into a temp struct */
  720.             MoveTo(scratchLine.start.h, scratchLine.start.v);       /* draw it */
  721.             LineTo(scratchLine.end.h, scratchLine.end.v);
  722.         }
  723.         HUnlock((Handle)(*theWind)->lineList);
  724.     }
  725.     /*  Any rectangles? */
  726.     if ((*theWind)->rectCount) {                            /* yes, draw 'em */
  727.         HLock((*theWind)->rectList);
  728.         scratchRectPtr = (Rect *)*((*theWind)->rectList);
  729.         for (qq = 0; qq < (*theWind)->rectCount; qq++) {
  730.             scratchRect = *(scratchRectPtr + qq);
  731.             FrameRect(&scratchRect);
  732.         }
  733.         HUnlock((*theWind)->rectList);
  734.     }
  735.     /* any ovals ? */
  736.     if ((*theWind)->ovalCount) {
  737.         HLock((*theWind)->ovalList);
  738.         for (qq = 0; qq < (*theWind)->ovalCount; qq++) {
  739.             scratchRectPtr = (Rect *)*((*theWind)->ovalList);
  740.             scratchRect = *(scratchRectPtr + qq);
  741.             FrameOval(&scratchRect);
  742.         }
  743.         HUnlock((*theWind)->ovalList);
  744.     }
  745.     if ((*theWind)->boxHandle != nil) {
  746.         Rect framer;
  747.         textSectionHandle tempTS = (*theWind)->textSections;
  748.         TEUpdate(&(*theWind)->textBox, (*theWind)->boxHandle);
  749.         framer = (*theWind)->textBox;
  750.         InsetRect(&framer, -3, -2);
  751.         FrameRect(&framer);
  752.         /* step through any possible sections, and border them as needful */
  753.         while (tempTS) {
  754.             if ((*tempTS)->bordered)
  755.                 BorderTextSection(tempTS);
  756.             tempTS = (*tempTS)->nextSection;
  757.         }
  758.     }
  759.     
  760.     /* Does the window currenlty have a selection for 'Publish'? */
  761.     if (theWindPtr == FrontWindow()) {
  762.         if ((*theWind)->hasSelection) {
  763.             PenSize(1, 1);
  764.             PenPat(qd.gray);
  765.             FrameRect(&(*theWind)->selectionRect);
  766.             PenPat(qd.black);
  767.             
  768.         }
  769.     }
  770.     if ((*theWind)->numSubs) {                              /* are we subscribed to anything? */
  771.         PicHandle *tempHand;
  772.         Handle *tempRHand;
  773.         Rect *tempRect;
  774.         HLock((*theWind)->subDataHandle);                   /* lock down and get the rectangles and */
  775.         HLock((*theWind)->subRects);                        /* current picture data for the subscribers this */
  776.         tempHand = (PicHandle *)*(*theWind)->subDataHandle;     /* window has */
  777.         tempRHand = (Handle *)*(*theWind)->subRects;
  778.         /* cast them into a handy form, and step through the list, drawing each */
  779.         for (qq = 0; qq < (*theWind)->numSubs; qq++) {
  780.             PicHandle tempPic;
  781.             tempPic = *tempHand;
  782.             /* ••••This following check is important!•••• */
  783.             /* No matter what data type you are subscribing to, the data MAY NOT */
  784.             /* be in your application at the time you get an update.  */
  785.             /* Updates have a higher event priority than AppleEvents, and you usually */
  786.             /* will get an update event after you show the 'Subscribe' dialog box and the */
  787.             /* user has subscribed to something.  */
  788.             /* What that means is that you may not have yet gotten the first Section Read */
  789.             /* event for this subscription, you have no data to display. */
  790.             if (GetHandleSize((Handle)tempPic) != nil) {
  791.                 HLock(*tempRHand);
  792.                 tempRect = (Rect *)*(*tempRHand);
  793.                 DrawPicture(tempPic, tempRect);
  794.                 HUnlock(*tempRHand);
  795.             }
  796.             tempHand += 1;
  797.             tempRHand += 1;
  798.         }
  799.         HUnlock((*theWind)->subDataHandle);
  800.         HUnlock((*theWind)->subRects);
  801.     }
  802.     if ((*theWind)->numPicts) {
  803.         Handle *tempPicPtr;
  804.         Handle *tempPicRect;
  805.         HLock((*theWind)->pictHandle);
  806.         HLock((*theWind)->pictRects);
  807.         tempPicPtr = (Handle *)*((*theWind)->pictHandle);
  808.         tempPicRect = (Handle *)*((*theWind)->pictRects);
  809.         for (qq = 0; qq < (*theWind)->numPicts; qq++) {
  810.             HLock(*tempPicRect);
  811.             DrawPicture((PicHandle)*tempPicPtr, (Rect *)(*(*tempPicRect)));
  812.             tempPicPtr += 1;
  813.             tempPicRect += 1;
  814.         }
  815.     }
  816.     /* Show publisher in this window if it's been clicked on lately */
  817.     if (theWindPtr == FrontWindow()) {
  818.         if (gShowPub) {
  819.             PenPat(qd.gray);                                /* 50% gray for publishers */
  820.             PenSize(3, 3);
  821.             FrameRect(&gShowPubRect);
  822.             PenPat(qd.black);
  823.             PenSize(1, 1);
  824.             grabRect = gShowPubRect;
  825.             grabRect.top = grabRect.bottom - 7;
  826.             grabRect.left = grabRect.right - 7;
  827.             PaintRect(&grabRect);
  828.             /* •••• NOTE:  I've taken the invert out of these areas because it got confusing for what */
  829.             /* I was publishing and subscribing.  Since we're dealing basically with bitmaps NOT */
  830.             /* with object-style graphiocs, the invert can be confusing.  */
  831.             /*           InsetRect(&gShowPubRect, 4, 4); */
  832.             /* invert the selection */
  833.             /*            InvertRect(&gShowPubRect);        */
  834.             /*            InsetRect(&gShowPubRect, -4, -4); */
  835.         }
  836.         if (gShowSub) {
  837.             PenPat(qd.dkGray);                              /* 75% gray for subscriptions */
  838.             PenSize(3, 3);
  839.             InsetRect(&gShowSubRect,-4,-4);
  840.             FrameRect(&gShowSubRect);
  841.             
  842.             PenPat(qd.black);
  843.             PenSize(1, 1);
  844.             /* same as NOTE above */
  845.             /*            InsetRect(&gShowSubRect, 4, 4); */
  846.             /*            InvertRect(&gShowSubRect); */
  847.             /*            InsetRect(&gShowSubRect, -4, -4); */
  848.             /* add a resizing grabber */
  849.             if (gResizeSub) {
  850.                 grabRect = gShowSubRect;
  851.                 grabRect.top = grabRect.bottom - 7;
  852.                 grabRect.left = grabRect.right - 7;
  853.                 
  854.                 PenPat(qd.black);
  855.                 if (theWindPtr != FrontWindow()) {
  856.                     EraseRect(&grabRect);
  857.                     FrameRect(&grabRect);
  858.                 } else {
  859.                     EraseRect(&grabRect);
  860.                     PaintRect(&grabRect);
  861.                 }
  862.             }
  863.             InsetRect(&gShowSubRect,4,4);
  864.         }
  865.         /* see if border showing is happening */
  866.         /* They optionally may have the 'Show All Borders' menu item checked, if so show */
  867.         /* the location of all the sections in this window */
  868.         if (gShowingAll) {
  869.             Rect borderRect;
  870.             /* show all pubs */
  871.             if ((*theWind)->numPubs) {
  872.                 Rect *tempRectPtr;
  873.                 HLock((*theWind)->pubRects);
  874.                 tempRectPtr = (Rect *)*(*theWind)->pubRects;
  875.                 PenPat(qd.gray);                            /* 50% gray for publishers */
  876.                 PenSize(3, 3);
  877.                 for (qq = 0; qq < (*theWind)->numPubs; qq++) {
  878.                     borderRect = *tempRectPtr;
  879.                     InsetRect(&borderRect, -4, -4);
  880.                     FrameRect(&borderRect);
  881.                     tempRectPtr += 1;
  882.                 }
  883.                 HUnlock((*theWind)->pubRects);
  884.             }
  885.             
  886.             /* show all subs */
  887.             if ((*theWind)->numSubs) {
  888.                 
  889.                 Handle *theRectsHandle;
  890.                 //            Debugger();
  891.                 HLock((*theWind)->subRects);                /* lock down the rect handle */
  892.                 /* cast it as a pointer to handles for reading ease */
  893.                 theRectsHandle = (Handle *)*(*theWind)->subRects;
  894.                 
  895.                 PenPat(qd.dkGray);                          /* 75% gray for subscriptions */
  896.                 PenSize(3, 3);
  897.                 for (qq = 0; qq < (*theWind)->numSubs; qq++) {
  898.                     
  899.                     HLock(*theRectsHandle);
  900.                     
  901.                     borderRect = *((Rect *)*(*theRectsHandle));
  902.                     InsetRect(&borderRect, -4, -4);
  903.                     FrameRect(&borderRect);
  904.                     HUnlock(*theRectsHandle);
  905.                     theRectsHandle += 1;
  906.                     
  907.                 }
  908.                 HUnlock((*theWind)->subRects);
  909.                 
  910.             }
  911.             /* and show all text sections */
  912.             if ((*theWind)->textSections) {
  913.                 textSectionHandle tempTS = (*theWind)->textSections;
  914.                 do {
  915.                     BorderTextSection(tempTS);
  916.                     tempTS = (*tempTS)->nextSection;
  917.                 } while (tempTS);
  918.                 
  919.             }
  920.             PenSize(1, 1);
  921.             PenPat(qd.black);
  922.         }
  923.     }
  924. }
  925.  
  926. /* end DrawFull */
  927.  
  928. /* AddLine adds a line to our window data structure */
  929. /* nowHandle is the window data structure handle */
  930. /* inLine is the line to add */
  931. void AddLine(windowCHandle nowHandle, myLine *inline)
  932. {
  933.     Handle temphand;
  934.     myLine *tempLinePtr;
  935.     HLock((Handle)nowHandle);
  936.     temphand = (Handle)(*nowHandle)->lineList;
  937.     HUnlock((Handle)temphand);
  938.     MySetHandleSize((Handle)temphand, (GetHandleSize(temphand) + sizeof(myLine)));
  939.     HLock((Handle)temphand);
  940.     tempLinePtr = (myLine *)*temphand;
  941.     tempLinePtr += (*nowHandle)->lineCount;
  942.     *tempLinePtr = *inline;
  943.     (*nowHandle)->lineCount++;
  944.     (*nowHandle)->windowDirty = true;
  945.     HUnlock((Handle)temphand);
  946.     HUnlock((Handle)nowHandle);
  947. }
  948.  
  949. /* end AddLine */
  950.  
  951. /* AddRect adds a rectangle  to our window data structure */
  952. /* nowHandle is the window data structure handle */
  953. /* inRect is the rect to add */
  954. void AddRect(windowCHandle nowHandle, Rect *inrect)
  955. {
  956.     Handle temphand;
  957.     Rect *tempRectPtr;
  958.     HLock((Handle)nowHandle);
  959.     temphand = (*nowHandle)->rectList;
  960.     HUnlock(temphand);
  961.     MySetHandleSize(temphand, (GetHandleSize(temphand) + sizeof(Rect)));
  962.     HLock(temphand);
  963.     tempRectPtr = (Rect *)*temphand;
  964.     tempRectPtr += (*nowHandle)->rectCount;
  965.     *tempRectPtr = *inrect;
  966.     (*nowHandle)->rectCount++;
  967.     (*nowHandle)->windowDirty = true;
  968.     HUnlock(temphand);
  969.     HUnlock((Handle)nowHandle);
  970. }
  971.  
  972. /* end AddRect */
  973.  
  974. /* AddTextBox adds a text editing box to our window data structure */
  975. /* nowHandle is the window data structure handle */
  976. /* inRect is the position to put the box in to add */
  977.  
  978. void AddTextBox(windowCHandle nowHandle, Rect *inrect)
  979. {
  980.     Rect framer;
  981.     HLock((Handle)nowHandle);
  982.     
  983.     (*nowHandle)->textBox = *inrect;
  984.     (*nowHandle)->windowDirty = true;
  985.     /* Create a TERecord to go here */
  986.     InsetRect(&(*nowHandle)->textBox, -3, -3);
  987.     (*nowHandle)->boxHandle = TENew(inrect, &(*nowHandle)->textBox);
  988.     TEActivate((*nowHandle)->boxHandle);
  989.     framer = (*nowHandle)->textBox;
  990.     InsetRect(&framer, -3, -2);
  991.     InvalRect(&framer);
  992.     HUnlock((Handle)nowHandle);
  993. }
  994.  
  995. /* end AddTextBox */
  996.  
  997. /* AddOval adds a oval  to our window data structure */
  998. /* nowHandle is the window data structure handle */
  999. /* inOval is the oval to add */
  1000. void AddOval(windowCHandle nowHandle, Rect *inoval)
  1001. {
  1002.     Handle temphand;
  1003.     Rect *tempRectPtr;
  1004.     HLock((Handle)nowHandle);
  1005.     temphand = (*nowHandle)->ovalList;
  1006.     HUnlock(temphand);
  1007.     MySetHandleSize(temphand, (GetHandleSize(temphand) + sizeof(Rect)));
  1008.     HLock(temphand);
  1009.     tempRectPtr = (Rect *)*temphand;
  1010.     tempRectPtr += (*nowHandle)->ovalCount;
  1011.     *tempRectPtr = *inoval;
  1012.     (*nowHandle)->ovalCount++;
  1013.     (*nowHandle)->windowDirty = true;
  1014.     HUnlock(temphand);
  1015.     HUnlock((Handle)nowHandle);
  1016. }
  1017.  
  1018. /* end AddOval */
  1019.  
  1020. /* AddSelection adds a selection rectangle  to our window data structure */
  1021. /* nowHandle is the window data structure handle */
  1022. /* inRect is the rect to add */
  1023. void AddSelection(windowCHandle nowHandle, Rect *inrect)
  1024. {
  1025.     HLock((Handle)nowHandle);
  1026.     (*nowHandle)->selectionRect = *inrect;
  1027.     (*nowHandle)->hasSelection = true;
  1028.     HUnlock((Handle)nowHandle);
  1029. }
  1030.  
  1031. /* end AddSelection */
  1032.  
  1033.  
  1034.  
  1035. /* ShowMe is just a handy place to display a string and a number. */
  1036. void ShowMe(Str255 in, OSErr aevtErr)
  1037. {
  1038.     Str255 theGuy;
  1039.     InitCursor();
  1040.     NumToString((long)aevtErr, theGuy);
  1041.     ParamText(in, theGuy, "\p ", "");
  1042.     Alert(129, nil);
  1043. }
  1044.  
  1045. /* DoDiskEvents just checks the error code from the disk mount, */
  1046. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  1047. /* You can do much more here if you care about what disks are */
  1048. /* in the drive */
  1049. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  1050. {
  1051.     short hival, loval, tommy;
  1052.     Point fredpoint =  {
  1053.         40, 40
  1054.     };
  1055.     hival = HiWord(dinfo);
  1056.     loval = LoWord(dinfo);
  1057.     if (hival != noErr)                                     /* something happened */ {
  1058.         tommy = DIBadMount(fredpoint, dinfo);
  1059.     }
  1060. }
  1061.  
  1062. /* AdjustCursor taken pretty much from TrafficLight, modified to use our cursors */
  1063. /* and to use local coordinates this time, for variety */
  1064. /*  Change the cursor's shape, depending on its position. This also calculates
  1065.     the region where the current cursor resides (for WaitNextEvent). If the
  1066.     mouse is ever outside of that region, an event would be generated, causing
  1067.     this routine to be called, allowing us to change the region to the region
  1068.     the mouse is currently in. If there is more to the event than just “the
  1069.     mouse moved”, we get called before the event is processed to make sure the
  1070.     cursor is the right one. In any (ahem) event, this is called again before
  1071.     we fall back into WNE.
  1072.     
  1073.  
  1074. */
  1075.  
  1076. void AdjustCursor(Point mouse, RgnHandle region, Boolean isAppleEvent)
  1077. {
  1078.     WindowPtr window, tempWindow;
  1079.     RgnHandle specialRgn;
  1080.     Rect globalPortRect;
  1081.     windowCHandle shortName;
  1082.     window = FrontWindow();                                 /* we only adjust the cursor when we are in front */
  1083.     if (window == gClipWindowPtr) {
  1084.         InitCursor();
  1085.         return;
  1086.     }
  1087.     if (gWindowCount == 0)
  1088.         return;                                             /* ignore also if we have no open doc windows */
  1089.     if ((!gInBackground) && (!IsDAWindow(window))) {
  1090.         if (isAppleEvent)
  1091.             return;                                         /* do no cursoring on AppleEvents */
  1092.         GetPort(&tempWindow);
  1093.         SetPort(window);
  1094.         /* calculate regions for different cursor shapes */
  1095.         specialRgn = NewRgn();
  1096.         /* calculate specialRgn */
  1097.         globalPortRect = window->portRect;
  1098.         RectRgn(specialRgn, &globalPortRect);
  1099.         SectRgn(specialRgn, window->visRgn, specialRgn);
  1100.         /* change the cursor and the region parameter */
  1101.         GlobalToLocal(&mouse);
  1102.         if (PtInRgn(mouse, specialRgn)) {
  1103.             short temp;
  1104.             shortName = (windowCHandle)GetWRefCon(window);
  1105.             temp = actsToIDs[(*shortName)->currentAction];
  1106.             SetMyCursor(temp);
  1107.             CopyRgn(specialRgn, region);
  1108.         } else {                                            /* outside */
  1109.             SetCursor(&qd.arrow);
  1110.         }
  1111.         /* get rid of our local regions */
  1112.         DisposeRgn(specialRgn);
  1113.         SetPort(tempWindow);
  1114.     }
  1115. }
  1116.  
  1117. /* end AdjustCursor*/
  1118.  
  1119.  
  1120. /* PullRect draws the rectangle or oval shape, and also resizes subscriptions */
  1121. void PullRect(windowCHandle theWind, Rect *startRect, Boolean isOval, Boolean useRect)
  1122. {
  1123.     Rect oldRect;
  1124.     Point endPoint;
  1125.     Rect tempHold;
  1126.     if (useRect) {
  1127.         oldRect = *startRect;
  1128.     } else {
  1129.         oldRect.top = startRect->top = oldRect.bottom = startRect->bottom = gERecord.where.v;
  1130.         oldRect.right = startRect->right = oldRect.left = startRect->left = gERecord.where.h;
  1131.     }
  1132.     tempHold = oldRect;
  1133.     PenMode(srcXor);                                        /* So we can rubberband */
  1134.     while (StillDown()) {                                   /* Keep doing this as long as the */
  1135.         /* user keeps the mouse down */
  1136.         GetMouse(&endPoint);                                /* Current mouse position in local */
  1137.         /* coordinates */
  1138.         startRect->right = endPoint.h;
  1139.         startRect->bottom = endPoint.v;
  1140.         if (!InTextBox(theWind, startRect)) {
  1141.             if (*startRect != oldRect) {                    /* redraw the rect only if the mouse moved  */
  1142.                 if (isOval) {
  1143.                     FrameOval(&oldRect);                    /* Erase (overdraw in Xor) the old oval */
  1144.                     FrameOval(startRect);
  1145.                 } else {
  1146.                     FrameRect(&oldRect);                    /* Erase (overdrw in Xor) the old rect */
  1147.                     FrameRect(startRect);                   /* draw the new rect */
  1148.                 }
  1149.                 oldRect = *startRect;
  1150.             }
  1151.         }
  1152.     }
  1153.     PenMode(srcCopy);
  1154.     /* don't let them shrink a subscriber 'til it disappears */
  1155.     if (((startRect->right - startRect->left) < 15) || ((startRect->bottom - startRect->top) < 15))
  1156.         *startRect = tempHold;
  1157. }
  1158.  
  1159. /* DoDocumentClick handles clicking in the content region of our */
  1160. /* document windows. */
  1161. void DoDocumentClick(WindowPtr twindow)
  1162. {
  1163.     
  1164.     /* if the window already was frontmost, take the right */
  1165.     /* action for this window */
  1166.     /* ••• NOTE: Normally, this is also the place where you would */
  1167.     /* update the modification date (mdDate)  of publishers */
  1168.     /* If the user takes an action across a published area, you */
  1169.     /* should update the modification time to flag yourself that this */
  1170.     /* edition needs to be sent.  This date/time will also show up in the */
  1171.     /* Options dialog for that publisher. But for the sake of clarity in this */
  1172.     /* sample, I am only changing the mod date on edition write (in files.c) */
  1173.     Point endPoint;
  1174.     Point oldendPoint;
  1175.     Rect startRect;
  1176.     Boolean wasInTB;
  1177.     windowCHandle shortname;
  1178.     short tempAct;
  1179.     Rect testRect;
  1180.     gCurrentWindow = twindow;
  1181.     shortname = (windowCHandle)GetWRefCon(gCurrentWindow);
  1182.     /* This handle is already locked on entry, from the dispatcher that got us here */
  1183.     
  1184.     tempAct = (*shortname)->currentAction;                  /* what are they doing? */
  1185.     SetPort(gCurrentWindow);                                /* make sure the port is good, I'm paranoid */
  1186.     GlobalToLocal(&gERecord.where);                         /* everything will be in local coordinate to this window */
  1187.     /* I don't want users to draw objects across my text box, so see if this click is in that thang */
  1188.     testRect.left = testRect.right = gERecord.where.h;
  1189.     testRect.right++;
  1190.     testRect.top = testRect.bottom = gERecord.where.v;
  1191.     testRect.bottom++;
  1192.     wasInTB = InTextBox(shortname, &testRect);
  1193.     if (!wasInTB || tempAct == kTextBox || tempAct == kNoAction) {
  1194.         switch (tempAct) {                                  /* switch off the action code */
  1195.             myLine tempLine;
  1196.             case kNoAction:
  1197.                 /* no menu items checked.  See if they clicked in a */
  1198.                 /* publisher or subcriber */
  1199.                 /* border a publisher or subscriber if they clicked in one */
  1200.                 if (!SearchPubs(gERecord.where) && !SearchSubs(gERecord.where)) {
  1201.                     /* if they didn't click in one, then erase the current selection */
  1202.                     /* Check to see if they're clicking in the TERecord.  This takes precidence over */
  1203.                     /* any other click */
  1204.                     if (wasInTB) {
  1205.                         /* treat this like a random click to de-border any PICT subscriptions that */
  1206.                         /* may be selected */
  1207.                         
  1208.                         DeBorderSelection();
  1209.                         /* check publisher stuff here */
  1210.                         TEClick(gERecord.where, gERecord.modifiers & shiftKey, (*shortname)->boxHandle);
  1211.                         if (!gShowingAll) {
  1212.                             textSectionHandle tempTS = (*shortname)->textSections;
  1213.                             Boolean anyOn = false;          /* for our invalidate check */
  1214.                             /* step through text sections and turn off flags */
  1215. //                            while (tempTS) {
  1216. //                                /* also check here to see if anything was bordered.  If it was, invalidate */
  1217. //                                /* the TE rectangle so the old borders will be erased.  If there */
  1218. //                                /* were NOT any, don't invalidate, so we don't strobe the user to */
  1219. //                                /* blindness */
  1220. //                                anyOn = anyOn | (*tempTS)->bordered;
  1221. //                                (*tempTS)->bordered = false;
  1222. //                                tempTS = (*tempTS)->nextSection;
  1223. //                            }
  1224. //                            if (anyOn)
  1225. //                                InvalRect(&(*(*shortname)->boxHandle)->viewRect);
  1226.                         }                                   /* see if the click was inside a subscriber */
  1227.                         CheckSectionHit();
  1228.                         
  1229.                     } else {
  1230.                         /* if it was a random click, dehilite the text selection if there is one */
  1231.                         if ((*shortname)->boxHandle != nil) {
  1232.                             TESetSelect((*(*shortname)->boxHandle)->selStart, (*(*shortname)->boxHandle)->selStart,
  1233.                                         (*shortname)->boxHandle);
  1234.                             /* Also, check to see if any borders are on in the TE box.  If so, turn them off.  */
  1235.                             /* That is, unless gSHowingAll is on.... */
  1236.                             /* and it's easiest just to invlaidate the terect */
  1237.                             InvalRect(&(*(*shortname)->boxHandle)->viewRect);
  1238.                             if (!gShowingAll) {
  1239.                                 textSectionHandle tempTS = (*shortname)->textSections;
  1240.                                 /* step through text sections and turn off flags */
  1241.                                 while (tempTS) {
  1242.                                     (*tempTS)->bordered = false;
  1243.                                     tempTS = (*tempTS)->nextSection;
  1244.                                 }
  1245.                             }
  1246.                         }
  1247.                         DeBorderSelection();
  1248.                     }
  1249.                     break;
  1250.                     case kDrawLine:
  1251.                         /* they want to draw a line in this window */
  1252.                         /* start and end points of the line set to the same val */
  1253.                         oldendPoint = endPoint = gERecord.where;
  1254.                         PenMode(srcXor);                    /* Xor so we can rubberband the line */
  1255.                         while (StillDown()) {               /* Keep doing this as long as the */
  1256.                             /* user keeps the mouse down */
  1257.                             GetMouse(&endPoint);            /* Current mouse position in local */
  1258.                             MakeRect(&gERecord.where, &endPoint, &testRect);
  1259.                             if (!InTextBox(shortname, &testRect)) {
  1260.                                 /* coordinates */
  1261.                                 if (endPoint != oldendPoint) {      /* only do this if the mouse moved so the line doesn't flicker */
  1262.                                     /* erase the old line (redraw in Xor mode ) */
  1263.                                     MoveTo(gERecord.where.h, gERecord.where.v);
  1264.                                     LineTo(oldendPoint.h, oldendPoint.v);
  1265.                                     /* draw the new line */
  1266.                                     MoveTo(gERecord.where.h, gERecord.where.v);
  1267.                                     LineTo(endPoint.h, endPoint.v);
  1268.                                     oldendPoint = endPoint;
  1269.                                 }
  1270.                             }
  1271.                         }                                   /* StillDown while */
  1272.                         PenMode(srcCopy);
  1273.                         /* They released the mouse.  Add the line they drew */
  1274.                         /* to our record */
  1275.                         tempLine.start = gERecord.where;
  1276.                         tempLine.end = endPoint;
  1277.                         /* see this function later in this file */
  1278.                         AddLine((windowCHandle)((WindowPeek)gCurrentWindow)->refCon, &tempLine);
  1279.                         /* changes the Undo menu item text */
  1280.                         SetUndo(kDrawLine, false);
  1281.                         break;                              /* end line case */
  1282.                         
  1283.                         /* they want to draw a rectangle in this window */
  1284.                     case kDrawRect:
  1285.                         /* start and end of rectangle set to the same val */
  1286.                         PullRect(shortname, &startRect, false, false);
  1287.                         /* Add it to our window */
  1288.                         AddRect((windowCHandle)((WindowPeek)gCurrentWindow)->refCon, &startRect);
  1289.                         SetUndo(kDrawRect, false);          /* Set undo menu item text to */
  1290.                         /* Undo Rectangle */
  1291.                         break;                              /* end rectangle case */
  1292.                         
  1293.                     case kDrawOval:
  1294.                         /* start and end of oval set to the same val */
  1295.                         PullRect(shortname, &startRect, true, false);
  1296.                         /* Add the oval to our window struct */
  1297.                         AddOval((windowCHandle)((WindowPeek)gCurrentWindow)->refCon, &startRect);
  1298.                         /* Set undo menu item text to Undo Oval */
  1299.                         SetUndo(kDrawOval, false);
  1300.                         break;
  1301.                     case kTextBox:
  1302.                         /* start and end of rectangle set to the same val */
  1303.                         PullRect(shortname, &startRect, false, false);
  1304.                         /* Add it to our window */
  1305.                         AddTextBox((windowCHandle)((WindowPeek)gCurrentWindow)->refCon, &startRect);
  1306.                         SetUndo(kCantUndo, false);          /* can't undo a text box */
  1307.                         SwitchChecks(kTextBox);
  1308.                         InitCursor();
  1309.                         /* Undo Rectangle */
  1310.                         break;
  1311.                     case kSelectStuff:
  1312.                         /* pretty much like drawrect, but */
  1313.                         /* the resulting rect can be published */
  1314.                         PullRect(shortname, &startRect, false, false);
  1315.                         PenPat(qd.gray);
  1316.                         FrameRect(&startRect);
  1317.                         PenPat(qd.black);
  1318.                         PenSize(1, 1);
  1319.                         AddSelection((windowCHandle)((WindowPeek)gCurrentWindow)->refCon, &startRect);
  1320.                         /* they can only select one rectangle, so clear the check */
  1321.                         /* and change the cursor back to an arrow */
  1322.                         SwitchChecks(kSelectStuff);
  1323.                         InitCursor();
  1324.                         gHasSelection = true;               /* flagging a selection available, see right */
  1325.                         SetUndo(kSelectItem - 1, false);        /* since the item on the menu is one more than our use, because of the divider */
  1326.                         /* before the MenuSelect call above to see how it's used */
  1327.                         break;
  1328.                         break;
  1329.                 } else {
  1330.                     unsigned long timeNow;
  1331.                     /* they did click in one, see if it is/was a double click please */
  1332.                     if ((gShowingSecHandle == lastSection) && (gShowingSecHandle != nil)) {
  1333.                         timeNow = TickCount();
  1334.                         if ((timeNow - lastSecClickTick) < GetDblTime()) {
  1335.                             /* it is a double click.  treat the same way as the menu selection for Options */
  1336.                             if (gERecord.modifiers & optionKey)
  1337.                                 MyGoToPublisher(lastSection);
  1338.                             else
  1339.                                 DoOptions(gShowingSecHandle);       /* in Subscribe.c. */
  1340.                             
  1341.                         } else {
  1342.                             /* not a double click.  Set up for the next pass */
  1343.                             lastSecClickTick = timeNow;
  1344.                             lastSection = gShowingSecHandle;
  1345.                         }
  1346.                     } else {
  1347.                         lastSecClickTick = timeNow;
  1348.                         lastSection = gShowingSecHandle;
  1349.                     }
  1350.                 }
  1351.         }
  1352.     }
  1353. }
  1354.  
  1355. /* end DoDocumentClick */
  1356.  
  1357. /* Various clipboard handling routines */
  1358. #pragma segment Main
  1359.  
  1360. /* This tries as hard as it can to resize a  handle, avoiding the problem SetHandleSize */
  1361. /* has when a block is surrounded by locked stuff.  */
  1362. /* Of course if you use this, you can only have one copy of the handle around and you */
  1363. /* always must reference that handle, since the master pointer contained within it */
  1364. /* can change during the ReallocHandle call.  But you should be doing that anyway (nag nag nag) */
  1365. OSErr MySetHandleSize(Handle theHandle, Size theSize)
  1366. {
  1367.     OSErr memErr;
  1368.     char state;
  1369.     Handle tempHand = theHandle;
  1370.     SetHandleSize(theHandle, theSize);
  1371.     memErr = MemError();
  1372.     if (!memErr)
  1373.         return(noErr);
  1374.     /* could not resize the handle.  Why? */
  1375.     if (memErr != memFullErr)
  1376.         return(memErr);                                     /* not something we can deal with */
  1377.     /* either the memory is really not available, or there is a locked pointer
  1378.     *   above the handle we're resizing.  We'll try seeing if the memory 
  1379.     *   is actually there first. */
  1380.     ShowMe("\p mem err", memErr);
  1381.     if (!(CompactMem(theSize) >= theSize))
  1382.         return(MemError());                                 /* memory really is full, bail */
  1383.     /* OK, memory is available somewhere.  Find it */
  1384.     HandToHand(&tempHand);                                  /* copy the handle */
  1385.     ReallocHandle(theHandle, theSize);                      /* resize by reallocation */
  1386.     HLock(tempHand);
  1387.     HLock(theHandle);
  1388.     BlockMove(*tempHand, *theHandle, GetHandleSize(theHandle));     /* only move the size of the target */
  1389.     HUnlock(theHandle);
  1390.     DisposHandle(tempHand);
  1391. }
  1392.  
  1393.  
  1394.  
  1395. /* InTextBox tells us if the rectangle passed intersects the text rectangle */
  1396. /* in the current window.  We use this for; */
  1397. /* 1) Seeing if the mouse click was in the TERect, so we can call TEClick */
  1398. /* 2) See if one of our drawing commands will overdraw the text, which is BaD */
  1399. Boolean InTextBox(windowCHandle inName, Rect *where)
  1400. {
  1401.     Rect temp;
  1402.     if ((*inName)->boxHandle == nil) {
  1403.         return(false);
  1404.     } else {
  1405.         return(SectRect(where, &(*inName)->textBox, &temp));
  1406.     }
  1407. }
  1408.  
  1409. /* MakeRect converts two points into a rect. */
  1410. void MakeRect(Point *aPoint, Point *bPoint, Rect *putRect)
  1411. {
  1412.     short temp;
  1413.     putRect->top = aPoint->v;
  1414.     putRect->left = aPoint->h;
  1415.     putRect->bottom = bPoint->v;
  1416.     putRect->right = bPoint->h;
  1417.     if (putRect->top > putRect->bottom) {
  1418.         temp = putRect->bottom;
  1419.         putRect->bottom = putRect->top;
  1420.         putRect->top = temp;
  1421.     }
  1422.     if (putRect->left > putRect->right) {
  1423.         temp = putRect->right;
  1424.         putRect->right = putRect->left;
  1425.         putRect->left = temp;
  1426.     }
  1427.     if (putRect->right == putRect->left)
  1428.         putRect->left++;
  1429.     if (putRect->bottom == putRect->top)
  1430.         putRect->bottom++;
  1431. }
  1432.  
  1433.  
  1434.  
  1435.  
  1436. void AppendString(Str255 target, Str255 appendIt)
  1437. {
  1438.     BlockMove((Ptr)(appendIt + 1), (Ptr)(target + (target[0])+1), appendIt[0]);
  1439.     target[0] += appendIt[0];
  1440. }
  1441.  
  1442. Boolean PureCursor(char theKey)
  1443. {
  1444.     register qq;
  1445.     char curChars[4] =  {
  1446.         kLeftArrow, kRightArrow, kUpArrow, kDownArrow
  1447.     };
  1448.     Boolean result = false;
  1449.     for (qq = 0; qq < 4; qq++) {
  1450.         if (theKey == curChars[qq])
  1451.             result = true;
  1452.     }
  1453.     return(result);
  1454.     
  1455. }
  1456.  
  1457. void DeBorderSelection(void)
  1458. {
  1459.     if (gShowPub) {
  1460.         gShowPub = false;
  1461.         gShowingSecHandle = nil;
  1462.         InvalRect(&gShowPubRect);
  1463.     } else {
  1464.         if (gShowSub) {
  1465.             gShowSub = false;
  1466.             gShowingSecHandle = nil;
  1467.             InvalRect(&gShowSubRect);
  1468.         }
  1469.     }
  1470. }
  1471.  
  1472.  
  1473.  
  1474. #pragma segment MyInit
  1475. /* StartStuff initializes the managers and does some other init stuff */
  1476. void StartStuff(void)
  1477. {
  1478.     extern void StartMenus();
  1479.     MaxApplZone();
  1480.     InitGraf((Ptr)&qd.thePort);
  1481.     InitFonts();
  1482.     InitWindows();
  1483.     InitMenus();
  1484.     TEInit();
  1485.     InitDialogs(nil);
  1486.     InitCursor();
  1487.     MoreMasters();
  1488.     /* See if AppleEvents and the Edition manager are available */
  1489.     InitAEStuff();                                          /* In AppleEventM.c */
  1490.     gHasEditionManager = (Gestalt(gestaltEditionMgrAttr, &aLong) == noErr);
  1491.     if (gHasEditionManager) {
  1492.         InitEditionPack();
  1493.         /* set up my opener routine, will be implemented later */
  1494.         /*      GetEditionOpenerProc(&gOriginalOpener);
  1495.                 SetEditionOpenerProc((EditionOpenerProcPtr)OpenMyFiles);
  1496.         */
  1497.         
  1498.     } else {
  1499.         Alert(kNoEditionManager, nil);                      /* tell 'em and exit */
  1500.         ExitToShell();
  1501.     }
  1502.     GetCurrentProcess(&gOurSN);                             /* grab our applications process serial number */
  1503.     /* so we can communicate (send appleevents) to */
  1504.     /* ourself easily */
  1505.     StartMenus();                                           /* load the menu bar and set up the menus */
  1506.     CreateClipBoard();
  1507.     /* ••• NOTE: I am not opening a document window here.  The application will wait for an */
  1508.     /* OAPP AppleEvent before opening a window.  This makes it a whole lot easier */
  1509.     /* to deal with ODOC events, since you needn't special case anything */
  1510. }
  1511.  
  1512. /* end StartStuff */
  1513.  
  1514. /* CreateClipBoard creates our invisible clipboard window at application */
  1515. /* start time, and keeps it open always.  Visibility is toggled from the edit menu, */
  1516. /* but the window always exists */
  1517. void CreateClipBoard(void)
  1518. {
  1519.     windowCHandle tempWC;
  1520.     
  1521.     /* open my clipboard window */
  1522.     gClipWindowPtr = GetNewWindow(kClipWindow, 0, (WindowPtr)-1);
  1523.     
  1524.     /* since I'm using the same function for my clipboard as for a document window, I have */
  1525.     /* to change some of the fields */
  1526.     ((WindowPeek)gClipWindowPtr)->refCon = NewHandle(sizeof(windowControl));        /* add our control structure to it */
  1527.     tempWC = (windowCHandle)GetWRefCon(gClipWindowPtr);     /* and put it where we can use it */
  1528.     HLock((Handle)tempWC);                                  /* lock it down */
  1529.     /* add pointers to our procedures for drawing, saving, and closing */
  1530.     (*tempWC)->drawMe = (ProcPtr)DrawClip;
  1531.     (*tempWC)->saveMe = (ProcPtr)nil;
  1532.     (*tempWC)->closeMe = (ProcPtr)CloseClip;
  1533.     (*tempWC)->clickMe = (ProcPtr)ClipClick;
  1534.     (*tempWC)->lineCount = nil;
  1535.     (*tempWC)->rectCount = nil;
  1536.     (*tempWC)->ovalCount = nil;
  1537.     (*tempWC)->currentAction = nil;
  1538.     (*tempWC)->undoAction = nil;
  1539.     (*tempWC)->hasSelection = false;
  1540.     (*tempWC)->windowDirty = false;
  1541.     (*tempWC)->boxHandle = nil;
  1542.     (*tempWC)->textSections = nil;
  1543.     gScrapData = NewHandle(0);
  1544.     UpdateScrap();
  1545. }
  1546.  
  1547. /* end CreateClipBoard */
  1548.  
  1549.  
  1550. #undef __SAMPMAIN__
  1551.